package modules.silix;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import miscellaneous.JCommanderUsageWrapper;
import miscellaneous.SequenceFileWriter;

import com.beust.jcommander.JCommander;

public class Silix {
	/* **************************************************************************** *
	 * 							CLASS VARIABLES										*
	 * **************************************************************************** */
	private String softwareName;
	private String resourcePath;
	private String resultPath;
	private String output;
	private String fastaFile;
	private String blastFile;

	/* **************************************************************************** *
	 * 							CLASS CONSTRUCTORS									*
	 * **************************************************************************** */
	public Silix() {
	}

	public Silix(String path, String output, String resourcepath, String fastaFile, String blastFile) {
		softwareName = "hifix";
		this.resourcePath = resourcepath;
		resultPath = path;
		this.fastaFile = fastaFile;
		this.blastFile = blastFile;
	}

	/* **************************************************************************** *
	 * 							CLASS PUBLIC FUNCTIONS								*
	 * **************************************************************************** */
	public void displayHelp() {
		String[] command = {resourcePath + softwareName, "--h"};
		runCommand(command);
	}

	public void setRelativePath(String resourcePath, String dataPath, String resultPath) {
		this.resourcePath = resourcePath;
		this.resultPath = resultPath;
	}

	public String[] makeCommand() {
		String[] command = {resourcePath + softwareName, resultPath + fastaFile, resultPath + blastFile, "-n", "-o", resultPath + output + ".fnodes"};
		return command;
	}

	public boolean runCommand(String[] command) {
		int 				exitVal;
		String 				line;
		Runtime 			runtime;
		Process 			process;
		InputStream 		stdin;
		InputStream 		stderr;
		BufferedReader 		bufferedreader;
		InputStreamReader 	inputstreamreader;

		try {
			runtime = Runtime.getRuntime();
			process = runtime.exec(command, null, null);
			stdin = process.getInputStream();
			inputstreamreader = new InputStreamReader(stdin);
			bufferedreader = new BufferedReader(inputstreamreader);
			while ( (line = bufferedreader.readLine()) != null)
				System.out.println(line);

			exitVal = process.waitFor();
			if(exitVal != 0) {
				stderr = process.getErrorStream();
				inputstreamreader = new InputStreamReader(stderr);
				bufferedreader = new BufferedReader(inputstreamreader);
				while ( (line = bufferedreader.readLine()) != null)
					System.out.println(line);
			}
			return true;
		} catch(Exception e) {
			System.out.println("Error in hclust: " + e.getMessage());
			System.exit(-1);
			return false;
		}
	}

	public String getModuleName() {
		return "silix";
	}

	public void main(String[] args) throws Exception {
		Parameters params;
		String path;
		String output;
		String fastaFile;
		String blastFile;
		String resourcepath;

		 try {

			 // ================ PARSE USER OPTIONS AND ARGUMENTS ================

			 params = new Parameters();
			 JCommander jc = new JCommander(params, args);

			 if (args.length == 0 || params.help) {
				 StringBuilder sb = new StringBuilder(65536);
				 sb.append(
						 "================================================================================\n" +
								 "hifix is ........... \n\n" +
								 "If you use this program in your research or for comparison reasons, please cite the \n" +
								 "following articles.\n" +
								 "References:\n" +
								 "    HomoCompara : A Comparative Study of Homology Inference Techniques and Methodologies \n" +
								 "    on Eukaryotic, Fungi, Bacteria and Simulated Datasets,\n" +
								 "    Ali RH, Muhammad SA and Lars Arvestad, 2014, doi: .................\n\n" +
								 "Releases, source code and tutorial: http://code.google.com/p/homocompara/\n\n" +
								 "License: GenFamClust is available under the New BSD License.\n" +
						 "================================================================================\n");
				 sb.append("Usage:\n" +
						 "    java -jar homocompara-X.Y.Z.jar hcluster [options] <args>\n");
				 JCommanderUsageWrapper.getUnsortedUsage(jc, params, sb);
				 System.out.println(sb.toString());
				 return;
			 }

			 path = params.path;
			 output = params.output;
			 resourcepath = params.resourcepath;
			 fastaFile = params.files.get(0);
			 blastFile = params.files.get(1);

			 if(!path.endsWith("/"))
				 path = path.concat("/");
			 if(!resourcepath.endsWith("/"))
				 path = resourcepath.concat("/");

			 if(params.executeconversiononly == false) {
				 Silix silix = new Silix(path, output, resourcepath, fastaFile, blastFile);
				 System.out.println("Running silix software ... Please wait. ");
				 silix.runCommand(silix.makeCommand());
				 System.out.println("Completed running silix software ... Converting to blastclust format ... Please wait. ");
				 ConvertSilixToBlastClust("silix", path, output + ".fnodes", output);
				 System.out.println("Completed Conversion.");
			 } else {
				 System.out.println("Converting to blastclust format ... Please wait. ");
				 ConvertSilixToBlastClust("silix", path, fastaFile, output);
				 System.out.println("Completed Conversion.");
			 }
		 } catch (Exception e) {
			 System.out.println("Data Preparator Failed : " + e.getMessage());
			 System.exit(-1);
		 }		
	}
	
	public void ConvertSilixToBlastClust(String program, String path, String fileName, String output) {
		String str;
		
		ArrayList<String> famName = new ArrayList<String>();
		ArrayList<String> protName = new ArrayList<String>();
		ArrayList<String> usedFamName = new ArrayList<String>();
		
		try{
			BufferedReader bufferedreader;
			bufferedreader = new BufferedReader(new FileReader(path + fileName));
			while ((str = bufferedreader.readLine()) != null) {
				String[] strArr = str.split("\t");
				famName.add(strArr[0]);
				protName.add(strArr[1]);				
			}
			
			for(int i = 0; i < protName.size(); i++) {
				String fam = famName.get(i);
				boolean checker = true;
				for(int j = 0; j < usedFamName.size(); j++) 
					if(fam.equals(usedFamName.get(j))) 
						checker = false;
				if(checker == true)
					usedFamName.add(fam);
			}
			
			for(int i = 0; i < usedFamName.size(); i++) {
				String fam = usedFamName.get(i);
				for(int j = 0; j < famName.size(); j++) 
					if(fam.equals(famName.get(j))) 
						SequenceFileWriter.writeAndAppendString(path, output + ".bcl", "\t" + protName.get(j));
				SequenceFileWriter.writeAndAppendLine(path, output + ".bcl", "");
			}
		} catch (Exception e) {
			System.out.println("Error: " + e.getMessage());
		}
	}
}
